#include "proc.h"

#include "input.h"
#include "pid.h"
#include <stdio.h>
#include <stdlib.h>

#include "flash.h"
#include "setting.h"

extern uint16_t g_settingTemperaturePowerValue;

extern uint16_t g_settingTemperatureStepValue;

extern uint32_t g_nowAdcValue;

extern uint16_t g_nowTemperatureValue;

extern ADC_HandleTypeDef hadc1;

extern PID_STRUCTURE *g_pidStructurePower;
extern PID_STRUCTURE *g_pidStructureBack;

extern volatile uint32_t g_updateUi;

extern uint8_t g_inputStatus;

extern double g_pidPowerValue;

extern TIM_HandleTypeDef htim2;

extern MONO_PriorityTimerQueue *tim1_queue;
extern MONO_PriorityTimerQueue *tim3_queue;
extern MONO_PriorityTimerQueue *power_process_queue;

extern double g_identifyHotRate;

extern SETTING_STRUCTURE *g_settings;

/**
 * @brief  Bluzzer程序
 */
MONO_PriorityTimerNode *bluzzerProccessNode;

// 设置ADC的值 从设置温度进行计算
uint32_t settingADCValue = 0;

// 设定的ADC值
double setpoint = 0;
// 上一次的ADC值
double pv = 0;

volatile uint8_t fire_status           = 0; // 加热状态指示
volatile uint8_t hot_indication_status = 0; // UI上火焰的状态

// 是否为第一次加热
uint8_t first_hot = 1;

void powerControlProcess()
{
    settingADCValue = g_settingTemperaturePowerValue * g_identifyHotRate;

    g_nowTemperatureValue = g_nowAdcValue / g_identifyHotRate;

    if (g_nowTemperatureValue < (g_settingTemperaturePowerValue - PID_SPLIT_TEMPERATURE_THRESHOLD))
    {
        g_pidStructurePower->pv       = pv;
        g_pidStructurePower->setpoint = settingADCValue;
        g_pidPowerValue               = pid_calculate(g_pidStructurePower);
        if (fire_status == 0)
        {
            fire_status = 1;
        }
    }
    else
    {
        g_pidStructureBack->pv       = pv;
        g_pidStructureBack->setpoint = settingADCValue;
        g_pidPowerValue              = pid_calculate(g_pidStructureBack);
        if (fire_status != 0)
        {
            fire_status = 0;
        }
    }

    if (g_nowTemperatureValue >= g_settingTemperaturePowerValue)
    {
        if (first_hot == 1)
        {
            first_hot = 0;
            MONO_PushNode(tim1_queue, bluzzerProccessNode);
        }
    }

    if (g_nowTemperatureValue > g_settingTemperaturePowerValue + 5)
    {
        g_pidStructurePower->_integral = 0;
        g_pidStructureBack->_integral  = 0;
    }

    pv = g_nowAdcValue;
}

static void oled_cmd(uint8_t i2c_cmd)
{
    uint8_t *cmd;
    cmd = &i2c_cmd;
    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT, cmd, 1, 100);
}

static void oled_data(uint8_t i2c_data)
{
    uint8_t *data;
    data = &i2c_data;
    HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT, data, 1, 100);
}

static void oled_origin(uint8_t x, uint8_t y)
{
    oled_cmd(0xb0 + y);
    oled_cmd(((x & 0xf0) >> 4) | 0x10);
    oled_cmd((x & 0x0f) | 0x01);
}

// 温度进度条指示数组 对应oled
uint8_t oled_index_temperature_array[100] = {0};
// 功率进度条指示数组
uint8_t oled_index_power_array[100] = {0};

// 用于判断是否可以移除火焰图标的标志
// 当暴力加热结束即变为0
uint8_t last_fire_status = 1;

extern ERROR_TYPE g_errorType;

void ScreenUpdateProcess()
{
    if (g_updateUi == UPDATE_UI_ALL)
    {
        oled_show_image(77, 3, 7);   // 大温度
        oled_show_image8(121, 7, 4); // 右下角小温度

        g_updateUi = (0x01 << UPDATE_UI_TEMPERATURE) | (0x01 << UPDATE_UI_SETTING_TEMPERATURE) |
                     (0x01 << UPDATE_UI_SETTING_STATUS);
    }

    if ((g_updateUi & (0x01 << UPDATE_UI_SETTING_TEMPERATURE)) != 0)
    {
        char tmp[6];
        sprintf(tmp, "%03d", g_settingTemperaturePowerValue);
        oled_show_string(52, 3, tmp, FONT_SIZE_BIG);
    }

    if ((g_updateUi & (0x01 << UPDATE_UI_TEMPERATURE)) != 0)
    {
        char tmp[6];
        sprintf(tmp, "%03d", g_nowTemperatureValue);
        if (g_nowTemperatureValue >= MAX_TEMPERATURE)
        {
            g_errorType = ADC_OVER_RANGE;
            errorHandler();
        }
        oled_show_string(101, 7, tmp, FONT_SIZE_SMALL);

        if (g_nowTemperatureValue < g_settingTemperaturePowerValue)
        {
            uint8_t index = (((double)g_nowTemperatureValue / g_settingTemperaturePowerValue) * 70);
            for (size_t i = 0; i < index; i += 2)
            {
                if (oled_index_temperature_array[i] != 1)
                {
                    oled_index_temperature_array[i] = 1;
                    oled_origin(i, 7);
                    oled_data(0xFF);
                    oled_data(0xFF);
                }
            }
            for (size_t i = index; i < 70; i += 2)
            {
                if (oled_index_temperature_array[i] != 0)
                {
                    oled_index_temperature_array[i] = 0;
                    oled_origin(i, 7);
                    oled_data(0x00);
                    oled_data(0x00);
                }
            }
        }
        else
        {
            // TODO BUG
            uint8_t index = g_nowTemperatureValue / MAX_TEMPERATURE * 30 + 70;
            for (size_t i = 72; i < index; i += 2)
            {
                if (oled_index_temperature_array[i] != 1)
                {
                    oled_index_temperature_array[i] = 1;
                    oled_origin(i, 7);
                    oled_data(0xFF);
                    oled_data(0xFF);
                }
            }
            for (size_t i = index; i < 102; i += 2)
            {
                if (oled_index_temperature_array[i] != 0)
                {
                    oled_index_temperature_array[i] = 0;
                    oled_origin(i, 7);
                    oled_data(0x00);
                    oled_data(0x00);
                }
            }
        }

        if (fire_status == 1)
        {
            if (hot_indication_status == 0)
            {
                // fire 1
                oled_show_image(95, 3, 3);
                hot_indication_status = 1;
            }
            else if (hot_indication_status == 1)
            {
                // fire 2
                oled_show_image(95, 3, 4);
                hot_indication_status = 0;
            }
        }
        else
        {
            // 防止
            if (last_fire_status != fire_status)
            {
                // null
                oled_show_image(95, 3, 0);
            }
        }

        last_fire_status = fire_status;
    }

    if ((g_updateUi & (0x01 << UPDATE_UI_SETTING_STATUS)) != 0)
    {
        if (g_inputStatus == 0)
        {
            // Setting
            g_pidStructurePower->_integral = 0;
            g_pidStructureBack->_integral  = 0;
            oled_show_image(35, 3, 2);
            if (g_settings->setting_temperature != g_settingTemperaturePowerValue ||
                g_settings->setting_step != g_settingTemperatureStepValue)
            {
                g_settings->setting_temperature = g_settingTemperaturePowerValue;
                g_settings->setting_step        = g_settingTemperatureStepValue;
                Flash_WriteData(DEFAULT_FLASH_START_ADDR, (uint16_t *)g_settings, sizeof(SETTING_STRUCTURE));
            }
        }
        else
        {
            // Lock
            oled_show_image(35, 3, 5);
        }
    }

    if ((g_updateUi & (0x01 << UPDATE_UI_POWER)) != 0)
    {
        char tmp[10];
        int  pidPwr = g_pidPowerValue / 4096 * 100;
        sprintf(tmp, "%03d%%", pidPwr);
        oled_show_string(105, 0, tmp, FONT_SIZE_SMALL);
        for (size_t i = 0; i < pidPwr; i += 2)
        {
            if (oled_index_power_array[i] != 1)
            {
                oled_index_power_array[i] = 1;
                oled_origin(i, 0);
                oled_data(0xFF);
                oled_data(0xFF);
            }
        }
        for (size_t i = pidPwr; i < 100; i += 2)
        {
            if (oled_index_power_array[i] != 0)
            {
                oled_index_power_array[i] = 0;
                oled_origin(i, 0);
                oled_data(0x00);
                oled_data(0x00);
            }
        }
    }
    g_updateUi = UPDATE_UI_NOTHING;
}

void adcConvertProcess()
{
    // 开始读取ADC
    HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_4);
    HAL_ADC_Start_IT(&hadc1);
}

void initProcesses()
{
    if (tim1_queue != NULL)
    {
        MONO_DeallocateQueueMemory(tim1_queue);
    }
    if (tim3_queue != NULL)
    {
        MONO_DeallocateQueueMemory(tim3_queue);
    }
    if (power_process_queue != NULL)
    {
        MONO_DeallocateQueueMemory(power_process_queue);
    }

    // 初始化优先级任务队列
    tim1_queue          = CreatePriorityTimerQueue();
    tim3_queue          = CreatePriorityTimerQueue();
    power_process_queue = CreatePriorityTimerQueue();

    // 创建屏幕刷新任务
    MONO_PriorityTimerNode *screenUpdateProcessNode =
        MONO__CreateQueueNode((MONO_NodeFunction_t)&ScreenUpdateProcess, 0, 1, 10, UINT8_MAX, 10, 0, NULL, NULL);

    MONO_PushNodeRelease(tim3_queue, screenUpdateProcessNode);
    // 全局任务
    bluzzerProccessNode = MONO__CreateQueueNode((MONO_NodeFunction_t)(&bluzzerSwitch), 1, 1, 0, 250, 1, 1, NULL, NULL);

    // -----> 功能性任务
    // 温度读取任务
    MONO_PriorityTimerNode *adcConvertProcessNode =
        MONO__CreateQueueNode((MONO_NodeFunction_t)(&adcConvertProcess), 0, 1, 0, UINT8_MAX, 20, 0, NULL,
                              (MONO_NodeFunction_t)adcConvertResultHandler);

    // 功率计算输出任务
    MONO_PriorityTimerNode *powerControlProcessNode =
        MONO__CreateQueueNode((MONO_NodeFunction_t)(&powerControlProcess), 0, 1, 10, UINT8_MAX, 20, 0, NULL,
                              (MONO_NodeFunction_t)pidResultHandler);

    MONO_PushNodeRelease(power_process_queue, adcConvertProcessNode);
    MONO_PushNodeRelease(power_process_queue, powerControlProcessNode);
}
